# /usr/bin/python
# ! -*- coding:UTF-8 -*-

from ProcessModel import ProcessModel
import time  # sleep用
import threading  # 线程
import random  # 产生随机数


class Processer(ProcessModel):
    # 定义需要用的变量
    # 每行上的按钮的个数
    NUMBER_OF_ITEM = 20

    # 定义并初始化一个保存所有按钮的数组
    btns = []

    # 定义一个保存已经选择的按钮的数组
    selected_btns = []

    # 判断是否已经连续下一步的flag
    continue_start = False

    # 默认的颜色
    DEFAULT_COLOR = "white"

    # 默认选中的颜色
    SELECTED_COLOR = "black"

    # 所有能更换的颜色
    COLORS = ["cyan", "azure", "gold", "orange", "violet", "blue", "salmon", "chocolate", "tan", "lime",
              "yellow", "green", "red", "grey", "black", "maroon", "silver", "brown"]

    # 定义当程序陷入无限循环的时候，循环多少次会终止
    MAX_LOOP_TIMES = 20

    def __init__(self):
        # 初始化btns
        for n_f_i_i in range(self.NUMBER_OF_ITEM):
            temp_x = []
            self.btns.append(temp_x)
            for n_f_i_j in range(self.NUMBER_OF_ITEM):
                self.btns[n_f_i_i].append(0)

    # 集体刷新已选择的按钮的显示
    def refresh_selected(self):
        for item in self.selected_btns:
            if item.get_selected():
                item.get_button()["background"] = self.SELECTED_COLOR
            else:
                item.get_button()["background"] = self.DEFAULT_COLOR

    # 刷新单个按钮
    def refresh_single(self, item):
        if item.get_selected():
            item.get_button()["background"] = self.SELECTED_COLOR
        else:
            item.get_button()["background"] = self.DEFAULT_COLOR

    # 定义按钮的事件
    def onclick(self, btn):
        if btn.get_button()["background"] == self.DEFAULT_COLOR:
            # btn.get_button()["background"] = "black"
            btn.set_selected(True)
            self.refresh_single(btn)
            self.selected_btns.append(btn)
        else:
            # btn.get_button()["background"] = "white"
            btn.set_selected(False)
            self.refresh_single(btn)
            self.selected_btns.remove(btn)

    def next_step(self):
        # 如果连续操作打开了，则关闭该按钮
        if not self.continue_start:
            self.execute_game()

    def execute_game(self):

        # 将每个selected的按钮周围的也加入到该selected_btns里
        all_around_btns = []  # 保存selected_btns中的所有按钮的周围的所有的按钮
        for ibtn in self.selected_btns:
            around_btns = self.list_around_cells(ibtn)
            all_around_btns += around_btns
        # 将all_around_btns添加到selected_btns中
        self.selected_btns += all_around_btns
        self.selected_btns = list(set(self.selected_btns))  # 去重
        # print "after added len", len(self.selected_btns)
        # self.print_all_selected_button()

        # 遍历已经选择了的按钮，判断每个已经选择了的按钮的周边的状态
        for btn in self.selected_btns:

            # 判断界限，将周边按钮加入selected_btns
            around_btns = self.list_around_cells(btn)

            # 计算周边活着的cell的数量(使用颜色判定，颜色是黑的才说明当前为活着)
            live_cell_number = 0
            for around in around_btns:
                if around.get_button()["background"] == self.SELECTED_COLOR:
                    live_cell_number += 1

            # 处理周边按钮，加入计算逻辑
            if live_cell_number == 3:
                btn.set_selected(True)
            elif live_cell_number == 2:
                pass
            else:
                btn.set_selected(False)

        # 所有的按钮遍历完成，根据selected属性更改颜色。
        self.refresh_selected()

        # 随后开始从已选择的cell（按钮）中去除死掉的cell
        self.selected_btns = filter(lambda x: x.get_selected(), self.selected_btns)  # 打印保存所有按钮的数组

    # 将该按钮周边按钮也加入selected_btn队列
    def list_around_cells(self, ibtn):

        i = ibtn.get_x()
        j = ibtn.get_y()

        around_btns = []  # 保存周边的按钮

        max_size = self.NUMBER_OF_ITEM - 2

        # 左上
        if i >= 1 and j >= 1:
            around_btns.append(self.btns[i - 1][j - 1])
        # 正上
        if i >= 1:
            around_btns.append(self.btns[i - 1][j])
        # 右上
        if i >= 1 and j <= max_size:
            around_btns.append(self.btns[i - 1][j + 1])
        # 正左
        if j >= 1:
            around_btns.append(self.btns[i][j - 1])
        # 正右
        if j <= max_size:
            around_btns.append(self.btns[i][j + 1])
        # 左下
        if i <= max_size and j >= 1:
            around_btns.append(self.btns[i + 1][j - 1])
        # 正下
        if i <= max_size:
            around_btns.append(self.btns[i + 1][j])
        # 右下
        if i <= max_size and j <= max_size:
            around_btns.append(self.btns[i + 1][j + 1])

        # 返回该按钮附近的按钮队列
        return around_btns

    # 开始，（包括暂停之后）
    def start(self):
        def continue_execute():
            length = len(self.selected_btns)
            index = 0
            while self.continue_start and length != 0:  # 优化，如果啥都没选择的话就不进行操作了
                self.execute_game()
                # 用一个if else 判断到了无限循环，细胞永生的情况，这个时候让线程终止
                if length != len(self.selected_btns):
                    length = len(self.selected_btns)
                    index = 0
                else:
                    index += 1
                    if index >= self.MAX_LOOP_TIMES:
                        self.continue_start = False
                # 每次循环等待时间
                time.sleep(0.2)

        self.continue_start = True
        # 优化，确保只执行一次
        if self.continue_start and len(self.selected_btns) != 0:
            t = threading.Thread(target=continue_execute, name="print_thread")
            t.start()

    # 暂停
    def pause(self):
        self.continue_start = False

    # 退出程序，执行某些操作。在界面结束前会执行此函数
    def quit(self):
        self.continue_start = False
        self.btns = None
        self.selected_btns = None
        # time.sleep(0.2)  # 等待fork出的线程结束

    # 清空当前内容，重新开始
    def clear(self):
        # 初始化已选择的按钮的状态（因为其他按钮的状态并没有改变，所以可以优化，不对其他按钮执行操作）
        for item in self.selected_btns:
            item.set_selected(False)

        self.refresh_selected()
        self.selected_btns = []  # 清空

    # 装载地图。读入文件名，打开文件处理内容
    def load_map(self, file):
        print ("readfile " + file.name)
        self.clear()  # 首先将当前地图清空
        try:
            for line in file.readlines():
                line = line.strip()  # 去除末尾的换行符
                pos = line.split(",")
                x = int(pos[0])
                y = int(pos[1])

                # 将每个读入的坐标对应的btn对象放入selected_btns中
                tmp = self.btns[x][y]
                tmp.set_selected(True)
                self.selected_btns.append(tmp)
        finally:
            if file:
                file.close()

        # 全添加进来之后，刷新面板
        self.refresh_selected()

    # 保存为地图
    def output_map(self, file):
        is_success = False
        try:
            for item in self.selected_btns:
                string = str(item.get_x()) + "," + str(item.get_y()) + "\n"
                file.write(string)

            is_success = True
        except:
            pass
        finally:
            if file:
                file.close()

        return is_success

    # 可改变颜色
    def change_color(self):
        selected_color = self.COLORS[random.randint(0, len(self.COLORS) - 1)]
        self.SELECTED_COLOR = selected_color
        print ("selected color", selected_color)
        self.refresh_selected()

    # 打印所有的按钮
    def print_all_button(self):
        print "*****number of buttons:", self.NUMBER_OF_ITEM * self.NUMBER_OF_ITEM, "*****"
        for ii in range(self.NUMBER_OF_ITEM):
            for jj in range(self.NUMBER_OF_ITEM):
                print self.btns[ii][jj]
        print "*****print finish******"

    # 打印已经选择的所有的按钮
    def print_all_selected_button(self):
        print "*****selected buttons:", len(self.selected_btns), "*****"
        for ii in range(len(self.selected_btns)):
            print self.selected_btns[ii]
        print "*****print finish******"
